/*
Copyright (C) 2010  Christoph Schnack 

    This file is part of Tribuit.

    Tribuit is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Tribuit is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Tribuit.  If not, see <http://www.gnu.org/licenses/>.
*/
package GuiTools;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.util.Collections;
import java.util.Vector;

import javax.imageio.ImageIO;
import javax.swing.*;

import OtherDialogs.SaveDialog;
import Settings.*;
import Storage.*;
import Wordcheck.CorrectImage;


/**
 * 
 * Provides general GUI functions.
 * 
 * @author Christoph Schnack
 *
 */

public class GuiTools{
	public static final String TRIBUITVERSION = "1.3.1";
	public static final Color BGCOLOR=new Color(255,126,0);
	public static final String NOTALLOWEDSIGNS=" # ~ ; % = : > < + ,";
	public static final String LOGO_TOY_COLORS = "204,51,0%102,102,0%160,240,20%0,153,153%102,0,102%51,0,204%0,153,51";
	public static final String BG_TOY_COLOR = "220,160,5";
	public static final String LOGO_DEFAULT_COLORS = "160,240,5%160,240,5%160,240,5%160,240,5%160,240,5%160,240,5%160,240,5";
	public static final String BG_BLACK_COLOR="1,1,1";
	public static final String LOGO_COLOURED_COLORS = "188,101,17%153,14,23%131,196,129%164,122,60%209,122,46%86,255,88%38,112,191";
	public static final String LOGO_GRAY_COLORS = "13,156,88%38,192,39%193,207,243%84,149,243%158,172,195%3,125,252%154,213,0";
	public static final String BG_GRAY_COLOR = "102,102,102";
	//this one for developing
	public static final String TRIBUITHOME = System.getProperties().getProperty("java.class.path").substring(0, (System.getProperties().getProperty("java.class.path").length() - 4));
	//this one for jar file
	//public static final String TRIBUITHOME = System.getProperties().getProperty("java.class.path").substring(0, (System.getProperties().getProperty("java.class.path").length() - 12));
	public static final String PATHTOPICTUREMAPS = TRIBUITHOME+File.separator+"pictureMaps";
	public static final String STATISTICFILEPATH = TRIBUITHOME+File.separator+"settings"+File.separator+"statistics.trib";
	private static final String[] ZOOMSTEPS = new String[]{"0.25","0.50","0.75","1.00","1.25","1.50","1.75","2.00","2.50","3.00"};
	public static final ImageIcon CORRECT_IMAGE = new ImageIcon(new CorrectImage());
	public static final Image MINI_PLUS_ICON = loadImageFromGraphics("miniPlusIcon.png");
	public static final Image MINI_PLUS_HOVERED_ICON = loadImageFromGraphics("miniPlusIconHovered.png");
	public static final Image MINI_PLUS_DISABLED_ICON = loadImageFromGraphics("miniPlusIconDisabled.png");
	public static final Image MINI_MULTI_PLUS_ICON = loadImageFromGraphics("miniMultiPlusIcon.png");
	public static final Image MINI_MULTI_PLUS_HOVERED_ICON = loadImageFromGraphics("miniMultiPlusIconHovered.png");
	public static final Image MINI_MULTI_PLUS_DISABLED_ICON = loadImageFromGraphics("miniMultiPlusIconDisabled.png");
	public static final Image MINI_EDIT_ICON = loadImageFromGraphics("miniEditIcon.png");
	public static final Image MINI_EDIT_HOVERED_ICON = loadImageFromGraphics("miniEditIconHovered.png");
	public static final Image MINI_EDIT_DISABLED_ICON = loadImageFromGraphics("miniEditIconDisabled.png");
	public static final Image MINI_MINUS_ICON = loadImageFromGraphics("miniMinusIcon.png");
	public static final Image MINI_MINUS_HOVERED_ICON = loadImageFromGraphics("miniMinusIconHovered.png");
	public static final Image MINI_MINUS_DISABLED_ICON = loadImageFromGraphics("miniMinusIconDisabled.png");
	static Vector<File> VOCFILES = new Vector<File>();
	static Vector<FileLock> VOCLOCKS = new Vector<FileLock>();
	static Vector<RandomAccessFile> VOCFOS = new Vector<RandomAccessFile>();
	static FileLock LOCK;
	static File FILE;
	static FileOutputStream FOS;
    /**
     * 
     * Generates the Tribuit-Icon
     * 
     * @return returns the Tribuit-Icon
     */
	public static Image getTribuitIcon(){
    	BufferedImage image = new BufferedImage(16, 16, BufferedImage.TYPE_INT_RGB);
    	Graphics g = image.createGraphics();
   		g.setColor(Color.black);
    	g.drawRect(0, 0, 15, 15);
    	g.setColor(Color.red);
    	g.fillOval(2, 2, 11, 11);
    	g.setColor(Color.white);
    	g.drawLine(5, 5, 9, 5);
    	g.drawLine(7, 5, 7, 11);
    	return image;
    }
	
	public static void lockVocFiles(){
		try{
			File dir = new File(GuiTools.TRIBUITHOME+File.separator+"vocs");
			String[] fileList = dir.list(new FilenameFilter() {
    		    public boolean accept(File d, String name) {
    		       return name.endsWith(".voc");
    		    }
			});
			if(fileList.length>0 && VOCLOCKS.size()==0){
				for(int r=0;r<fileList.length;r++){
					VOCFILES.add(new File(GuiTools.TRIBUITHOME+File.separator+"vocs"+File.separator+fileList[r]));
					VOCFOS.add(new RandomAccessFile(VOCFILES.elementAt(r),"rw"));
					VOCLOCKS.add(VOCFOS.elementAt(r).getChannel().tryLock());
				}
			}
		}
		catch(Exception e){
			e.printStackTrace();
		}
	}
	
	public static Dimension getScreenSize(){
		return Toolkit.getDefaultToolkit().getScreenSize();
	}
	
	public static Image loadImage(String path){
		try{return ImageIO.read(new File(path));}
		catch(Exception e){
			e.printStackTrace();
			return null;
		}
	}
	
	public static Image loadImageFromGraphics(String name){
		try{return ImageIO.read(new File(TRIBUITHOME+File.separator+"graphics"+File.separator+name));}
		catch(Exception e){
			e.printStackTrace();
			return null;
		}
	}
	
	public static void unlockVocFiles(){
		if(VOCLOCKS.size()>0){
			try{
				for(int i=0;i<VOCLOCKS.size();i++){
					VOCLOCKS.elementAt(i).release();
					VOCFOS.elementAt(i).close();
				}
				VOCFILES.clear();
				VOCLOCKS.clear();
				VOCFOS.clear();
			}
			catch(Exception e){}
		}
	}
    
    /**
     * Checks if changes on MAINVOC are made and/or saved and exits eventually. 
     * Exits if nothing was CHANGED and if changes are SAVED, asks for unsaved exit if changed and not saved
     */

    public static void exitTribuit(Storage MAINVOC,TribuitFrame MAINFRAME,Settings SET){
    	if(!MAINVOC.isChanged()){
    		try {
    			LOCK.release();
    			FOS.close();
    			FILE.delete();
    		}catch(Exception e){e.printStackTrace();}
    		MAINFRAME.dispose();
    		if(SET.isVerbose())System.out.println("#########EXIT TRIBUIT############");
    		System.exit(0);
    	}
    	else{
    		askForUnsavedExit(MAINVOC,MAINFRAME,SET);
        }
    }
    
    /**
     * Shows an error message.
     * 
     * @param lang language instance
     * @param parentComponent 
     * @param textFieldName
     */
    public static void showEmptyOrInvalidInputWarning(Language lang,Component parentComponent,String textFieldName){
    	JLabel errorLabel = new JLabel(lang.getErrorInTextField()+" '"+textFieldName+"' !");
    	errorLabel.setFont(new Font(Font.SANS_SERIF,Font.BOLD,15));
    	JPanel panel = new JPanel(new GridBagLayout());
    	GridBagConstraints gbc = new GridBagConstraints();
    	gbc.anchor = GridBagConstraints.NORTHWEST;
    	gbc.fill = GridBagConstraints.BOTH;
    	panel.add(errorLabel,gbc);
    	gbc.gridy = 1;
    	gbc.insets = new Insets(20,0,0,0);
    	panel.add(new JLabel(lang.getEmptyOrInvalidInput()),gbc);
    	gbc.insets = new Insets(10,0,0,0);
    	gbc.gridy = 2;
    	panel.add(new JLabel(NOTALLOWEDSIGNS),gbc);
    	JOptionPane.showMessageDialog(parentComponent, panel, lang.getError(), JOptionPane.WARNING_MESSAGE);
    }
    
    /**
     * The result depends on a FileLock on a temporary file. If it is not locked already, it will be created and locked.
     * 
     * @return true if file is already locked
     */
    static public boolean isAnotherInstanceRunning() {
		try {
			FILE = new File(GuiTools.TRIBUITHOME+File.separator+"settings"+File.separator+"tribuitRunning.tmp");
			FOS = new FileOutputStream(FILE);
			FileChannel fc = FOS.getChannel();
			LOCK = fc.tryLock();
			if (LOCK == null) {
				fc.close();
				FOS.close();
				return true;
			}
			FILE.deleteOnExit();
		}
		catch (Exception e) {
			return false;
		}
		return false;
	}

    /**
     * 
     * Asks whether aborting Tribuit with or without saving
     */
    
    public static void askForUnsavedExit(Storage MAINVOC,TribuitFrame MAINFRAME,Settings set){
    	Language LANG = set.getLanguage();
    	String[] opts = {LANG.getQuit(),LANG.getSaveAndExit(),LANG.getCancel()};
    	SaveDialog sd = new SaveDialog(MAINVOC,set,LANG.getExitUnsaved()+"?");
    	if(!sd.getCanceled()){
    		MAINFRAME.dispose();
			System.exit(0);
    	}
    }
    /**
     * Returns false only if one of the not allowed characters was found.
     * 
     * @param st string to test
     * @return result
     */
    public static boolean checkInput(String st){
    	String[] NOTALLOWEDCHARS = {"#","~",";","%","=",":",">","<","+",","};
    	if((!st.equals("")) || (st!=null)){
    		for(int i=0;i<NOTALLOWEDCHARS.length;i++){
    			if(st.contains(NOTALLOWEDCHARS[i]))return false;
    		}
    	}
    	return true;
    }
    
    public static String[] sortAndIndexArray(String[] source){
    	Vector<String> result = new Vector<String>();
    	if(source!=null && source.length>0){
    		Vector<String> sourceCopy = new Vector<String>();
        	for(String s : source){
        		sourceCopy.add(s);
        	}
    		Collections.sort(sourceCopy,String.CASE_INSENSITIVE_ORDER);
    		String currentFirstLetter,lastFirstLetter="";
        	for(String s : sourceCopy){
        		currentFirstLetter = (s.charAt(0)+"").toUpperCase();
        		if(!lastFirstLetter.equals(currentFirstLetter)){
        			result.add(currentFirstLetter);
        			lastFirstLetter = currentFirstLetter;
        		}
        		result.add(s);
        	}
    	}
    	result.trimToSize();
    	return result.toArray(new String[]{});
    }
    
    public static Vector<String> sortAndIndexVector(Vector<String> source){
    	Vector<String> result = new Vector<String>();
    	if(source!=null && source.size()>0){
    		Collections.sort(source,String.CASE_INSENSITIVE_ORDER);
    		String currentFirstLetter,lastFirstLetter="";
        	for(String s : source){
        		currentFirstLetter = (s.charAt(0)+"").toUpperCase();
        		if(!lastFirstLetter.equals(currentFirstLetter)){
        			result.add(currentFirstLetter);
        			lastFirstLetter = currentFirstLetter;
        		}
        		result.add(s);
        	}
    	}
    	result.trimToSize();
    	return result;
    }
    
    public static String[] getZOOMSTEPS(){
    	return ZOOMSTEPS;
    }
}//GuiTools


